# CSP HTML Webpack Plugin

[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/slackhq/csp-html-webpack-plugin/blob/master/LICENSE)
[![npm](https://img.shields.io/npm/v/csp-html-webpack-plugin.svg)](https://www.npmjs.com/package/csp-html-webpack-plugin)
[![Code Style](https://img.shields.io/badge/code%20style-prettier-brightgreen.svg)](https://github.com/prettier/prettier)
[![Build Status](https://travis-ci.org/slackhq/csp-html-webpack-plugin.svg?branch=master)](https://travis-ci.org/slackhq/csp-html-webpack-plugin)
[![codecov](https://codecov.io/gh/slackhq/csp-html-webpack-plugin/branch/master/graph/badge.svg?token=cBemDmnz85)](https://codecov.io/gh/slackhq/csp-html-webpack-plugin)

## About

This plugin will generate meta content for your Content Security Policy tag and input the correct data into your HTML template, generated by [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin/).

All inline JS and CSS will be hashed, and inserted into the policy.

## Installation

Install the plugin with npm:

```
npm i --save-dev csp-html-webpack-plugin
```

## Basic Usage

In the plugins section of your webpack config file, include the following:

```
new HtmlWebpackPlugin()
new CspHtmlWebpackPlugin()
```

## Configuration

This `CspHtmlWebpackPlugin` accepts 2 params with the following structure:

- `{object}` Policy (optional) - a flat object which defines your CSP policy. Valid keys and values can be found on the [MDN CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) page. Values can either be a string or an array of strings.
- `{object}` Additional Options (optional) - a flat object with the optional configuration options:
  - `{boolean|Function}` enabled - if false, or the function returns false, the empty CSP tag will be stripped from the html output.
    - The `htmlPluginData` is passed into the function as it's first param.
    - If `enabled` is set the false, it will disable generating a CSP for all instances of `HtmlWebpackPlugin` in your webpack config.
  - `{string}` hashingMethod - accepts 'sha256', 'sha384', 'sha512' - your node version must also accept this hashing method.
  - `{object}` hashEnabled - a `<string, boolean>` entry for which policy rules are allowed to include hashes
  - `{object}` nonceEnabled - a `<string, boolean>` entry for which policy rules are allowed to include nonces
  - `{Function}` processFn - allows the developer to overwrite the default method of what happens to the CSP after it has been created
    - Parameters are:
      - `builtPolicy`: a `string` containing the completed policy;
      - `htmlPluginData`: the `HtmlWebpackPlugin` `object`;
      - `$`: the `cheerio` object of the html file currently being processed

The plugin also adds a new config option onto each `HtmlWebpackPlugin` instance:

- `{object}` cspPlugin - an object containing the following properties:
  - `{boolean}` enabled - if false, the CSP tag will be removed from the HTML which this HtmlWebpackPlugin instance is generating.
  - `{object}` policy - A custom policy which should be applied only to this instance of the HtmlWebpackPlugin
  - `{object}` hashEnabled - a `<string, boolean>` entry for which policy rules are allowed to include hashes
  - `{object}` nonceEnabled - a `<string, boolean>` entry for which policy rules are allowed to include nonces
  - `{Function}` processFn - allows the developer to overwrite the default method of what happens to the CSP after it has been created
    - Parameters are:
      - `builtPolicy`: a `string` containing the completed policy;
      - `htmlPluginData`: the `HtmlWebpackPlugin` `object`;
      - `$`: the `cheerio` object of the html file currently being processed

#### Order of Precedence:

Note that policies and `hashEnabled` / `nonceEnabled` are merged in the following order:

```
> HtmlWebpackPlugin cspPlugin.policy
> CspHtmlWebpackPlugin policy
> CspHtmlWebpackPlugin defaultPolicy
```

If 2 policies have the same key/policy rule, the former policy will override the latter policy. Entries in a specific rule will not be merged; they will be replaced.

This is useful if you need different policy rules / processing functions for different `HtmlWebpackPlugin` instances
in the same webpack config.

#### Default Policy:

```
{
  'base-uri': "'self'",
  'object-src': "'none'",
  'script-src': ["'unsafe-inline'", "'self'", "'unsafe-eval'"],
  'style-src': ["'unsafe-inline'", "'self'", "'unsafe-eval'"]
};
```

#### Default Additional Options:

```
{
  enabled: true
  hashingMethod: 'sha256',
  hashEnabled: {
    'script-src': true,
    'style-src': true
  },
  nonceEnabled: {
    'script-src': true,
    'style-src': true
  },
  processFn: defaultProcessFn
}
```

#### Full Configuration with all options:

Note that you don't have to include the same section in both `HtmlWebpackPlugin` and `CspHtmlWebpackPlugin`.
See the [Order of Precedence](#order-of-precedence) section above.

```
new HtmlWebpackPlugin({
  cspPlugin: {
    enabled: true,
    policy: {
      'base-uri': "'self'",
      'object-src': "'none'",
      'script-src': ["'unsafe-inline'", "'self'", "'unsafe-eval'"],
      'style-src': ["'unsafe-inline'", "'self'", "'unsafe-eval'"]
    },
    hashEnabled: {
      'script-src': true,
      'style-src': true
    },
    nonceEnabled: {
      'script-src': true,
      'style-src': true
    },
    processFn: defaultProcessFn
  }
});

new CspHtmlWebpackPlugin({
  'base-uri': "'self'",
  'object-src': "'none'",
  'script-src': ["'unsafe-inline'", "'self'", "'unsafe-eval'"],
  'style-src': ["'unsafe-inline'", "'self'", "'unsafe-eval'"]
}, {
  enabled: true,
  hashingMethod: 'sha256',
  hashEnabled: {
    'script-src': true,
    'style-src': true
  },
  nonceEnabled: {
    'script-src': true,
    'style-src': true
  },
  processFn: defaultProcessFn
})
```

## Contribution

Contributions are most welcome! Please see the included contributing file for more information.

## License

This project is licensed under MIT. Please see the included license file for more information.
